package com.huilan.base.esl.service.redis;

import cn.hutool.core.util.StrUtil;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedissonUtil {
    @Autowired
    public RedissonClient redisson;


    /**
     * @param map  内存map
     * @param key  map-key redis-hash-key
     * @param item redis-hash-item
     * @Description
     * @Return java.lang.Object
     * @Author liuwc
     * @Date 2020/10/21 9:12
     */
    public Object getFromMapWithRedis(Map map, String key, String item) {
        Object o = map.get(key);
        if (StrUtil.isEmptyIfStr(o)) {
            o = hGet(key, item);
            map.put(key, o);
        }
        return o;
    }

    //------------------------------------------rlo-----------------------------------------------------
    // 获取rlo 对象
    public <T> T getRlo(Class<T> tClass,String id){
        RLiveObjectService liveObjectService = redisson.getLiveObjectService();
        T t = liveObjectService.get(tClass, id);
        if (t == null){
            liveObjectService.persist(tClass);
            t = liveObjectService.get(tClass, id);
        }
        return t;
    }

    //------------------------------------------lock-----------------------------------------------------
    public RLock getLock(String key) {
        RLock lock = redisson.getLock(key);
        return lock;
    }


    //------------------------------------------base-----------------------------------------------------

    //递增
    public long incr(String key) {
        return incr(key, 1);
    }

    public long incr(String key, long num) {
        RAtomicLong atomicLong = redisson.getAtomicLong(key);
        return atomicLong.addAndGet(num);
    }

    public boolean expire(String key, long time, TimeUnit timeUnit) {
        RBucket<Object> bucket = redisson.getBucket(key);
        return bucket.expire(time, timeUnit);
    }

    public boolean expire(String key, long time) {
        return expire(key, time, TimeUnit.SECONDS);
    }

    public boolean hasKey(String key) {
        RBucket<Object> bucket = redisson.getBucket(key);
        return bucket.isExists();
    }

    public void delKey(String... key) {
        if (key.length == 1) {
            delKey(key[0]);
        } else if (key.length > 1) {
            delKeyBatch(key);
        }
    }
//    public void delKey(List<RemoveKey> keys) {
//        if (keys == null || keys.size()==0){
//            return;
//        }
//        RBatch batch = redisson.createBatch(BatchOptions.defaults().skipResult());
//        keys.forEach(s->{
//            List<Object> item = s.getItem();
//            if (item == null || item.size() == 0) {
//                RBucketAsync<Object> bucket = batch.getBucket(s.getKey());
//                bucket.deleteAsync();
//            } else {
//                RemoveKey.KeyType type = s.getType();
//                switch (type) {
//                    case set:
//                        RSetAsync<Object> set = batch.getSet(s.getKey());
//                        s.getItem().forEach(i->set.removeAsync(i));
//                        break;
//                    case hash:
//                        RMapAsync<Object, Object> map = batch.getMap(s.getKey());
//                        s.getItem().forEach(i->map.removeAsync(i));
//                        break;
//                    case list:
//                        RListAsync<Object> list = batch.getList(s.getKey());
//                        s.getItem().forEach(i->list.removeAsync(i));
//                        break;
//                    case string:
//                        RBucketAsync<Object> bucket = batch.getBucket(s.getKey());
//                        bucket.deleteAsync();
//                        break;
//                }
//            }
//        });
//        batch.executeAsync();
//    }


    public void delKey(String key) {
        RBucket<Object> bucket = redisson.getBucket(key);
        bucket.delete();
    }

    public void delKeyBatch(String... key) {
        RBatch batch = redisson.createBatch(BatchOptions.defaults().skipResult());
        for (String str : key) {
            RBucketAsync<Object> bucket = batch.getBucket(str);
            bucket.deleteAsync();
        }
        batch.execute();
    }

    public void delKeyBatchAsync(String... key) {
        RBatch batch = redisson.createBatch(BatchOptions.defaults().skipResult());
        for (String str : key) {
            RBucketAsync<Object> bucket = batch.getBucket(str);
            bucket.deleteAsync();
        }
        batch.executeAsync();
    }


    //------------------------------------------string-----------------------------------------------------
    public void set(String key, Object value) {
        RBucket<Object> bucket = redisson.getBucket(key);
        bucket.set(value);
    }

    public void set(String key, Object value, long time) {
        set(key, value, time, TimeUnit.SECONDS);
    }

    public void set(String key, Object value, long time, TimeUnit timeUnit) {
        RBucket<Object> bucket = redisson.getBucket(key);
        bucket.set(value, time, timeUnit);
    }


    public Object get(String key) {
        RBucket<Object> bucket = redisson.getBucket(key);
        return bucket.get();
    }
    public List getBatch(List<String> keys) {
        RBatch batch = redisson.createBatch();
        keys.stream().forEach(s->{
            RBucketAsync<Object> bucket = batch.getBucket(s);
            bucket.getAsync();
        });
        return batch.execute().getResponses();
    }


    public Object getAndDel(String key) {
        RBucket<Object> bucket = redisson.getBucket(key);
        return bucket.getAndDelete();
    }


    //------------------------------------------hash-----------------------------------------------------
    // hget
    public Object hGet(String key, Object item) {
        RMap<Object, Object> map = redisson.getMap(key);
        return map.get(item);
    }

    public Object hGet(HashRO hashRO) {
        return hGet(hashRO.getKey(), hashRO.getItem());
    }

    public Map<Object, Object> hGetAll(String key) {
        RMap<Object, Object> map = redisson.getMap(key);
        return map.readAllMap();
    }

    public List hGetAllBatch(List<String> keys) {
        RBatch batch = redisson.createBatch();
        keys.forEach(s -> {
            RMapAsync<Object, Object> map = batch.getMap(s);
            map.readAllMapAsync();
        });
        return batch.execute().getResponses();
    }

    // hHas
    public boolean hHas(String key, String item) {
        RMap<Object, Object> map = redisson.getMap(key);
        return map.containsKey(item);
    }
    // hIncr
    public long hIncr(String key, String item) {
        return hIncr(key,item,1);
    }
    public long hIncr(String key, String item,long num) {
        RMap<Object, Object> map = redisson.getMap(key);
        return Long.valueOf( map.addAndGet(item, num)+"");
    }
    // hset
    public Object hSet(String key, Object item, Object v) {
        RMap<Object, Object> map = redisson.getMap(key);
        return map.put(item, v);
    }

    public Object hSet(HashRO hashRO) {
        return hSet(hashRO.getKey(), hashRO.getItem(), hashRO.getT());
    }

    public void hSetBatch(List<HashRO> hashROS) {
        RBatch batch = redisson.createBatch(BatchOptions.defaults().skipResult());
        hashROS.forEach(s -> {
            RMapAsync<Object, Object> map = batch.getMap(s.getKey());
            map.putAsync(s.getItem(), s.getT());
        });
        batch.execute();
    }

    public void hSetBatchAsync(List<HashRO> hashROS) {
        RBatch batch = redisson.createBatch(BatchOptions.defaults().skipResult());
        hashROS.forEach(s -> {
            RMapAsync<Object, Object> map = batch.getMap(s.getKey());
            map.putAsync(s.getItem(), s.getT());
        });
        batch.executeAsync();
    }

    // hdel
    public Object hDel(String key, Object item) {
        RMap<Object, Object> map = redisson.getMap(key);
        return map.remove(item);
    }

    public void hDel(HashRO hashRO) {
        hDel(hashRO.getKey(), hashRO.getItem());
    }

    public void hDelBatch(List<HashRO> hashROS) {
        RBatch batch = redisson.createBatch(BatchOptions.defaults().skipResult());
        hashROS.forEach(s -> {
            RMapAsync<Object, Object> map = batch.getMap(s.getKey());
            map.removeAsync(s.getItem());
        });
        batch.execute();
    }

    public void hDelBatchAsync(List<HashRO> hashROS) {
        RBatch batch = redisson.createBatch(BatchOptions.defaults().skipResult());
        hashROS.forEach(s -> {
            RMapAsync<Object, Object> map = batch.getMap(s.getKey());
            map.removeAsync(s.getItem());
        });
        batch.executeAsync();
    }

    //------------------------------------------list-----------------------------------------------------
    public boolean lSet(String key, Object v) {
        RList<Object> list = redisson.getList(key);
        return list.add(v);
    }
    public void lFastSet(String key, Object v,int index) {
        RList<Object> list = redisson.getList(key);
        list.fastSet(index,v);
    }

    public boolean lSetAll(String key, List v) {
        RList<Object> list = redisson.getList(key);
        return list.addAll(v);
    }
    public List lGetAll(String key) {
        RList<Object> list = redisson.getList(key);
        return list.readAll();
    }

    public boolean lDel(String key, Object v) {
        RList<Object> list = redisson.getList(key);
        return list.remove(v);
    }

    public int lSize(String key) {
        RList<Object> list = redisson.getList(key);
        return list.size();
    }



    //------------------------------------------deque-----------------------------------------------------

    public void dqAddFirst(String key, Object v) {
        RDeque<Object> deque = redisson.getDeque(key);
        deque.addFirst(v);
    }
    public void dqAddLast(String key, Object v) {
        RDeque<Object> deque = redisson.getDeque(key);
        deque.addLast(v);
    }

    public void dqAddAll(String key, List list) {
        RDeque<Object> deque = redisson.getDeque(key);
        deque.addAll(list);
    }
    public Object dqPop(String key) {
        RDeque<Object> deque = redisson.getDeque(key);
        return deque.poll();
    }
    public List<Object> dqPop(String key,int num) {
        RDeque<Object> deque = redisson.getDeque(key);
        return deque.poll(num);
    }

    public Object dqPopLast(String key) {
        RDeque<Object> deque = redisson.getDeque(key);
        return deque.pollLast();
    }
    public List<Object> dqPopLast(String key,int num) {
        RDeque<Object> deque = redisson.getDeque(key);
        return deque.pollLast(num);
    }


    //------------------------------------------queue-----------------------------------------------------
    public Object qPop(String key) {
        RQueue<Object> queue = redisson.getQueue(key);
        return queue.poll();
    }
    public boolean qAdd(String key,Object v) {
        RQueue<Object> queue = redisson.getQueue(key);
        return queue.add(v);
    }
    public void qAddAll(String key, List list) {
        RQueue<Object> queue = redisson.getQueue(key);
        queue.addAll(list);
    }


    //------------------------------------------set-----------------------------------------------------
    //sSet
    public boolean sSet(String key, Object v) {
        RSet<Object> set = redisson.getSet(key);
        return set.add(v);
    }

    //sGet
    public Set<Object> sGetAll(String key) {
        RSet<Object> set = redisson.getSet(key);
        return set.readAll();
    }

    //sDel
    public boolean sDel(String key, Object v) {
        RSet<Object> set = redisson.getSet(key);
        return set.remove(v);
    }
    // sHas
    public boolean sHas(String key, Object v) {
        RSet<Object> set = redisson.getSet(key);
        return set.contains(v);
    }

    public int sSize(String key) {
        RSet<Object> set = redisson.getSet(key);
        return set.size();
    }

    //------------------------------------------script-----------------------------------------------------
    //加载脚本
    public String load(String s) {
        RScript script = redisson.getScript();
        return script.scriptLoad(s);
    }

    /**
     * @param shaDigest  sha
     * @param returnType 返回类型
     * @param keys
     * @param values
     * @Description 执行脚本 sha
     * @Return java.lang.Object
     * @Author liuwc
     * @Date 2020/10/21 11:00
     */
    public Object evalSha(String shaDigest, RScript.ReturnType returnType, List<Object> keys, Object... values) {
        return evalSha(RScript.Mode.READ_WRITE, shaDigest, returnType, keys, values);
    }

    public Object evalSha(RScript.Mode mode, String shaDigest, RScript.ReturnType returnType, List<Object> keys, Object... values) {
        return redisson.getScript().evalSha(mode, shaDigest, returnType, keys, values);
    }


}
